/*
 * Copyright (c) 2016, LI BO/Alex All rights reserved.
 * 
 * http://blog.sina.com.cn/alex4java
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hyts.infodb.config;

import com.hyts.infodb.error.ApplicationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.context.support.WebApplicationObjectSupport;

import javax.servlet.http.HttpServletRequest;

/**
 * @ClassName: SpringContextUtil
 * @Description: 实现不限地区不限地点的获取<br>	
 * 				 Spring上下文范围内的对象Bean<br>	
 * 				 SpringContextUtil工具类用于<br>
 * 				  获取Spring容器中的对象信息
 * @author: 李博/Alex
 * @date: 2017-1-22 下午4:43:56
 */
@Component
@Configuration
@Slf4j
public class SpringContextConfiguration extends WebApplicationObjectSupport{
	
	/**
	 * @fieldName: applicationContext
	 * @fieldType: ApplicationContext
	 * @Description: 定义ApplicationContext变量操作
	 */
	private static ApplicationContext applicationContext = null; 

	
	
	/************************在任何环境下 适合采用的方法***********************************************************/
	/**
	 * 可以继承 ApplicationContextObject
	 * 		   WebApplicationContextObject
	 * 		   ApplicationContextAware	
	 */
	
	@Override
	protected void initApplicationContext(ApplicationContext context) {
		super.initApplicationContext(context);
		if(SpringContextConfiguration.applicationContext == null)
			SpringContextConfiguration.applicationContext = context;
		log.debug("获取注入对应的ApplicationContext对象到priv.libo.web.tools.SpringContextUtil中");
		log.debug("调用priv.libo.web.tools.SpringContextUtil.getGlobalBean方法即可操作获取对应的对象");
	}
	
	/**
	 * @Title: getGlobalBean
	 * @Description: 获取对应的数据类型即可
	 * @param beanName
	 * @param clazz
	 * @return
	 * @return: T
	 */
	public static <T> T getGlobalBean(String beanName,Class<T> clazz){
		//判断参数是否为空！
		if(StringUtils.isEmpty(beanName)) {
			String message = "传入的Spring容器对象BeanName为空!";
			throw new ApplicationException(message);
		}
		if(StringUtils.isEmpty(clazz)) {
			String message = "传入的Spring容器对象clazz为空!";
			throw new ApplicationException(message);
		}
		return applicationContext.getBean(beanName, clazz);
	}
	
	/**
	 * @Title: getGlobalBean
	 * @Description: 获取对应的数据类型即可
	 * @param beanName
	 * @return
	 * @return: T
	 */
	public static <T> Object getGlobalBean(String beanName){
		//判断参数是否为空！
		if(StringUtils.isEmpty(beanName)) {
			String message = "传入的Spring容器对象BeanName为空!";
			throw new ApplicationException(message);
		}
		return applicationContext.getBean(beanName);
	}
	
	
	/**
	 * @Title: getGlobalBean
	 * @Description: 获取对应的数据类型即可
	 * @param clazz
	 * @return
	 * @return: T
	 */
	public static <T> T getGlobalBean(Class<T> clazz){
		//判断参数是否为空！
		if(StringUtils.isEmpty(clazz)) {
			String message = "传入的Spring容器对象clazz为空!";
			throw new ApplicationException(message);
		}
		return applicationContext.getBean(clazz);
	}
	
	/*	
	@Override
	protected void initServletContext(ServletContext servletContext) {
	}*/
	
	/* (non Javadoc)
	 * @Title: isContextRequired
	 * @Description: 判断是否属于上下文范围内的实现方法
	 * @return
	 * @see org.springframework.web.context.support.WebApplicationObjectSupport#isContextRequired()
	 */
	@Override
	protected boolean isContextRequired() {
		return super.isContextRequired();
	}
	
	/************************HttpServlet web容器环境下 适合采用的方法***********************************************************/
	/**
	 * @Title: getBean(适用于Controller层结构)
	 * @Description: 根据HttpServletRequest对象和 beanName 获取 对应的Spring 管理的对象	<br>
	 * 				   获取失败时抛出异常
	 * @param request
	 * @param beanName
	 * @return
	 * @return: ApplicationContext
	 */
	public static final <T> T getBean(HttpServletRequest request,String beanName,Class<T> clazz){
		//判断参数是否为空！
		if(StringUtils.isEmpty(beanName)) {
			String message = "传入的Spring容器对象BeanName为空!";
			throw new ApplicationException(message);
		}
		if(request == null) {
			String message = "传入的Web容器对象HttpServletRequest对象为!";
			throw new ApplicationException(message);
		}
		return WebApplicationContextUtils.getRequiredWebApplicationContext(request.getSession().getServletContext()).getBean(beanName,clazz);
	}
	
	/**
	 * @Title: getBean(适用于Controller层结构)
	 * @Description: 根据HttpServletRequest对象和 beanName 获取 对应的Spring 管理的对象	<br>
	 * 				   获取失败时抛出异常
	 * @param request
	 * @param beanName
	 * @return
	 * @return: T
	 */
	public static final <T> Object getBean(HttpServletRequest request,String beanName){
		//判断参数是否为空！
		if(StringUtils.isEmpty(beanName)) {
			String message = "传入的Spring容器对象BeanName为空!";
			throw new ApplicationException(message);
		}
		if(request == null) {
			String message = "传入的Web容器对象HttpServletRequest对象为!";
			throw new ApplicationException(message);
		}
		return WebApplicationContextUtils.getRequiredWebApplicationContext(request.getSession().getServletContext()).getBean(beanName);
	}
	
	/**
	 * @Title: getBeanQuiet
	 * @Description: 根据HttpServletRequest对象和 beanName 获取 对应的Spring 管理的对象	<br>
	 * 				   获取失败时返回null
	 * @param request
	 * @param beanName
	 * @return
	 * @return: ApplicationContext
	 */
	public static final <T> Object getBeanQuiet(HttpServletRequest request,String beanName,Class<T> clazz){
		//判断参数是否为空！
		if(StringUtils.isEmpty(beanName)) {
			String message = "传入的Spring容器对象BeanName为空!";
			throw new ApplicationException(message);
		}
		if(request == null) {
			String message = "传入的Web容器对象HttpServletRequest对象为!";
			throw new ApplicationException(message);
		}
		return WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext()).getBean(beanName,clazz);
	}

	
	/**
	 * @Title: getBeanQuiet
	 * @Description: 根据HttpServletRequest对象和 beanName 获取 对应的Spring 管理的对象	<br>
	 * 				   获取失败时返回null
	 * @param request
	 * @param beanName
	 * @return
	 * @return: Object
	 */
	public static final <T> Object getBeanQuiet(HttpServletRequest request,String beanName){
		//判断参数是否为空！
		if(StringUtils.isEmpty(beanName)) {
			String message = "传入的Spring容器对象BeanName为空!";
			throw new ApplicationException(message);
		}
		if(request == null) {
			String message = "传入的Web容器对象HttpServletRequest对象为!";
			throw new ApplicationException(message);
		}
		return WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext()).getBean(beanName);
	}
	
	
}
